{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests  # 爬虫\n",
    "import re       # 正则\n",
    "import time     # 控制爬虫休眠\n",
    "import random\n",
    "import csv      # 保存"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "class IQiYi:\n",
    "    def __init__(self):\n",
    "        \"\"\"初始化方法-只执行一次，作用：初始化对象：url\\headers\"\"\"\n",
    "        self.url = \"https://mesh.if.iqiyi.com/portal/pcw/rankList/comSecRankList?v=1&device=3a011f94751f8bce1a0da4a7e8d40391&auth=&uid=&ip=202.108.14.240&refresh=0&server=false&page_st=0&tag=0&category_id=2&date=&pg_num={}&next_pos=\"\n",
    "        self.headers = {\n",
    "            \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36\",\n",
    "            \"Referer\": \"https://www.iqiyi.com/ranks1/2/0\"\n",
    "        }\n",
    "        self.f = open('爱奇艺电视剧热播榜.csv', 'a', newline='', encoding='utf-8')       # 打开文件,创建一个存放数据的文件表\n",
    "        self.writer = csv.writer(self.f)        # 初始化写入对象\n",
    "        name = [('标题', '描述', '上映年份', '标签', '主演', '弹幕', '实时热度')]     # 定义表格标题\n",
    "        self.writer.writerows(name)     # 将表格标题写入文件表\n",
    "        self.all_film_list = []     # 定义一个大的空列表，用来存储所有的电视剧信息\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "  def get_html(self, url):\n",
    "        \"\"\"爬取获取目标网站的网页内容\"\"\"\n",
    "        html = requests.get(url=url, headers=self.headers).text     # 基于url和请求头执行爬取，得到html内容\n",
    "        self.parse_html(html)       # 将爬取得到的内容送入解析"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "  def parse_html(self, ht):\n",
    "        \"\"\"对爬取到的html内容进行正则解析\"\"\"\n",
    "        # 定义正则表达式\n",
    "        re_ex = '\"title\":\"(.*?)\".*?\"desc\":\"(.*?)\".*?\"tags\":\"(.*?)/(.*?)/(.*?)\".*?\"bulletIndex\":\"(.*?)\".*?\"mainIndex\":\"(.*?)\"'\n",
    "        # 编译对象，创建一个demo-样板\n",
    "        demo = re.compile(re_ex, re.S)  # re.S匹配包含\\n在内的所以字符\n",
    "        # 基于创建好的demo去第一步爬取到的html内容中依次查找，找到后就追加到re_list列表\n",
    "        re_list = demo.findall(ht)\n",
    "        # 解析结束后送入保存方法\n",
    "        self.save_html(re_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "  def save_html(self, re_list):\n",
    "        \"\"\"将解析的内容保存到定义的空列表\"\"\"\n",
    "        for r in re_list:\n",
    "            item = (\n",
    "                r[0].strip(),  # strip()截取左右两边的空白串\n",
    "                r[1].strip(),\n",
    "                r[2].strip(),\n",
    "                r[3].strip(),\n",
    "                r[4].strip(),\n",
    "                r[5].strip(),\n",
    "                r[6].strip()\n",
    "            )\n",
    "            self.all_film_list.append(item)     # 每处理完一部剧，加入新列表中\n",
    "            print(item)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    " def main(self):\n",
    "        \"\"\"主函数执行循环页面爬取\"\"\"\n",
    "        print(\"====开始爬取爱奇艺电视剧热播榜====\")\n",
    "        for i in range(1,5):\n",
    "            stime = random.randint(1, 5)\n",
    "            print(\"休眠{}秒后，开始第{}次爬取\".format(stime, i))\n",
    "            time.sleep(stime)  # 控制爬虫爬取频次-休眠\n",
    "            total_url = self.url.format(i)      # 完善url\n",
    "            self.get_html(total_url)        # 调用爬取函数\n",
    "        self.writer.writerows(self.all_film_list)  # 写入数据到文件\n",
    "        \n",
    "        self.f.close()  # 关闭文件\n",
    "        print(\"=========爬取结束========\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "ename": "AttributeError",
     "evalue": "'IQiYi' object has no attribute 'main'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-10-e14ef75c7176>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      2\u001b[0m     \u001b[1;31m# 创建类的实例\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      3\u001b[0m     \u001b[0msp\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mIQiYi\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 4\u001b[1;33m     \u001b[0msp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmain\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m: 'IQiYi' object has no attribute 'main'"
     ]
    }
   ],
   "source": [
    "if __name__ == '__main__':\n",
    "    # 创建类的实例\n",
    "    sp = IQiYi()\n",
    "    sp.main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
